/*
 * Created by Jaren at 2021/12/17 19:29
 */
import 'dart:typed_data';
import 'package:inmotion_protocol/common/error.dart';
import 'package:inmotion_protocol/common/file.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';

class SettingsResponse {
  Error _error = Error.success;
  String _message = "Succeed.";

  ProductModel? _productModel;
  VersionWrapper? _version;

  SettingsResponse(this._error, this._productModel, this._version, [this._message = '']);

  SettingsResponse.success();

  SettingsResponse.timeout() {
    _error = Error.timeout;
    _message = "Timeout";
  }

  SettingsResponse.notNow() {
    _error = Error.notNow;
    _message = "notNow";
  }

  SettingsResponse.protocolError([String message = 'Protocol error.']) {
    _error = Error.protocol;
    _message = message;
  }

  SettingsResponse.invalidParam() {
    _error = Error.invalidParam;
    _message = "invalidParam";
  }

  SettingsResponse.unknown() {
    _error = Error.unknown;
    _message = "Unknown";
  }

  Error get error => _error;

  ProductModel? get productModel => _productModel;

  VersionWrapper? get version => _version;

  bool isSuccess([bool includeSuccessCached = true]) {
    if (includeSuccessCached) return _error == Error.success || _error == Error.successCached;
    return _error == Error.success;
  }

  @override
  String toString() {
    return 'SettingsResponse{error: $_error, message: $_message}';
  }

  SettingsResponse.fromBytes(Uint8ClampedList bytes, [int offset = 0]);
}

enum Error { success, successCached, repeatedOperation, invalidParam, unsupported, notNow, noPermission, internalError, timeout, protocol, unknown }

class GeneralCtrlResponse extends SettingsResponse {
  GeneralCtrlResponse(Error error, ProductModel? productModel, VersionWrapper? version) : super(error, productModel, version);

  static Error compactError(int error) {
    if (error == 0) return Error.success;
    if (error == 1) return Error.invalidParam;
    if (error == 2) return Error.unsupported;
    if (error == 3) return Error.notNow;
    if (error == 4) return Error.noPermission;
    if (error == 5) return Error.internalError;
    return Error.unknown;
  }
}

abstract class AbsCalibrationResultResponse extends SettingsResponse {
  AbsCalibrationResultResponse(ProductModel? productModel, VersionWrapper? version) : super(Error.success, productModel, version);

  bool isCalibrating({int? which});

  bool isCalibrateSucceed({int? which});

  bool isCalibrateFailed({int? which});

  bool isCalibrateTimeout({int? which});
}

class FileResponse {
  int fileHandle = 0;
  int originError = 0;
  FileError error = FileError.success;
  String message = "Succeed.";

  FileResponse.byOriginError(this.originError);

  FileResponse.success({int originError = 0, String message = 'Succeed.'}) {
    error = FileError.success;
  }

  bool isSuccess() {
    return error == FileError.success;
  }

  static FileError getFileErrorByOriginError(int originError) {
    switch (originError) {
      case 0:
        return FileError.success;
      case 1:
        return FileError.fileNotFound;
      case 2:
        return FileError.unsupported;
      case 3:
        return FileError.conflict;
      case 4:
        return FileError.fileOpenedTooMuch;
      case 5:
        return FileError.invalidHandle;
      case 6:
        return FileError.fileSysError;
      case 7:
        return FileError.ioError;
      case 8:
        return FileError.invalidParam;
      case 9:
        return FileError.sysError;
      case 10:
        return FileError.cannotExecuteNow;
      case 11:
        return FileError.noPermission;
    }
    return FileError.unknown;
  }
}

class FileListResponse extends FileResponse {
  int index = 0;
  int remain = 0;
  List<File> files = [];

  FileListResponse.byOriginError(int originError) : super.byOriginError(originError);

  static FileListResponse create(int error, int index, int remain, List<File> files) {
    FileListResponse response = FileListResponse.byOriginError(error);
    response.index = index;
    response.remain = remain;
    response.files.addAll(files);
    return response;
  }
}
